package org.example.memora.service.serviceImpl;

import lombok.extern.slf4j.Slf4j;
import org.example.memora.common.result.Result;
import org.example.memora.entity.Post;
import org.example.memora.entity.PostLike;
import org.example.memora.entity.PostLikeStat;
import org.example.memora.mapper.PostLikeMapper;
import org.example.memora.mapper.PostLikeStatMapper;
import org.example.memora.mapper.PostMapper;
import org.example.memora.service.PostLikeService;
import org.hibernate.annotations.Cache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.connection.stream.RecordId;
import org.springframework.data.redis.connection.stream.StreamRecords;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


import java.time.Duration;
import java.time.Instant;
import java.util.*;

@Slf4j
@Service
public class PostLikeServiceImpl implements PostLikeService {

    @Autowired
    private PostLikeMapper postLikeMapper;
    @Autowired
    private PostLikeStatMapper postLikeStatMapper;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private PostMapper postMapper;

    @Override
    public Result<?> getLikedPostsByUser(Long userId) {
        List<PostLike> likedPosts = postLikeMapper.selectByUserId(userId);
        if (likedPosts.isEmpty()) {
            return Result.error("你还没有点赞过任何帖子");
        }
        return Result.success(likedPosts);
    }



    @Transactional
    @Override
    public Result<?> likePost(Long userId, String postId) {
        //TODO：可以考虑缓存穿透问题
        // Redis 键定义
        String redisRecordKey = "post:like:record:" + postId;
        String redisCountKey = "post:like:count:" + postId;

        // 检查 Redis 集合中是否已存在该用户的点赞记录
        Boolean alreadyLiked = redisTemplate.opsForSet().isMember(redisRecordKey, String.valueOf(userId));
        if (alreadyLiked != null && alreadyLiked) {
            return Result.error("已点赞，不能重复点赞");
        } else {
            // 补充校验数据库：防止缓存数据缺失导致重复点赞
            PostLike exist = postLikeMapper.selectByUserAndPost(userId, postId);
            if (exist != null) {
                return Result.error("已点赞，不能重复点赞");
            }
        }

        // 将点赞记录先写入 Redis（集合中保证唯一性）
        redisTemplate.opsForSet().add(redisRecordKey, String.valueOf(userId));
        redisTemplate.expire(redisRecordKey, Duration.ofMinutes(30));


        // 更新 Redis 中的点赞计数（原子自增）
        Boolean countKeyExists = redisTemplate.hasKey(redisCountKey);
        if (countKeyExists != null && countKeyExists) {
            // 如果 redis 中存在该计数，直接加 1
            redisTemplate.opsForValue().increment(redisCountKey, 1);
        } else {
            // 如果不存在，则从数据库加载初始值
            PostLikeStat stat = postLikeStatMapper.selectByPrimaryKey(postId);
//            if(stat==null){
//                return Result.error("缓存和数据库都不存在数据");
//            }
            int initialCount = (stat != null) ? stat.getLikeCount() : 0;
            // 将初始值存入 Redis
            redisTemplate.opsForValue().set(redisCountKey, String.valueOf(initialCount));
            // 然后再进行自增操作
            redisTemplate.opsForValue().increment(redisCountKey, 1);
        }
        Map<String, String> message = new HashMap<>();
        message.put("userId", userId.toString());
        message.put("postId", postId);
        message.put("action", "like");
        message.put("timestamp", String.valueOf(System.currentTimeMillis()));
        //redisTemplate.opsForStream().add("stream:post:like", message);
        // 写入 Stream，并设置 maxlen 自动裁剪（最多保留最近 10000 条）
        // 写入 Stream
        redisTemplate.opsForStream()
                .add(StreamRecords.mapBacked(message).withStreamKey("stream:post:like"));

// 手动裁剪（注意：这个是非原子操作）
        redisTemplate.opsForStream().trim("stream:post:like", 10);  // 或 trim(..., true) 近似裁剪

        return Result.success(1, "点赞成功");
    }

    @Override
    @Transactional
    public Result<?> unlikePost(Long userId, String postId) {
        // Redis 键定义
        String redisRecordKey = "post:like:record:" + postId;
        String redisCountKey = "post:like:count:" + postId;

        // 检查 Redis 集合中是否已存在该用户的点赞记录
        Boolean alreadyLiked = redisTemplate.opsForSet().isMember(redisRecordKey, String.valueOf(userId));
        if ( !alreadyLiked) {
            PostLike exist = postLikeMapper.selectByUserAndPost(userId, postId);
            if (exist == null) {
                return Result.error("未点赞，不能取消点赞");
            }
        }
        if(postLikeMapper.selectByUserAndPost(userId, postId)!=null){
            // 删除
            postLikeMapper.deleteLike(userId, postId);
        }
        Boolean exists = redisTemplate.hasKey(redisCountKey);
        if (exists != null && exists) {
            // 键存在，可以选择进一步判断值是否有效，例如非空且大于0
            String value = redisTemplate.opsForValue().get(redisCountKey);
            if (value != null && Integer.parseInt(value) > 0) {
                redisTemplate.opsForValue().decrement(redisCountKey, 1);
            }
        } else {
            PostLikeStat stat=postLikeStatMapper.selectByPrimaryKey(postId);
            int initialCount = (stat != null) ? stat.getLikeCount() : 0;
            if(initialCount==0){
                return Result.error("点赞数已为0，不能取消点赞了，请检查逻辑是否有问题");
            }
            int count=postMapper.selectLikeCountInt(postId);
            if(count>0){
                postMapper.incrementPostLikeCount(postId,-1);
            }
            // 将初始值存入 Redis
            redisTemplate.opsForValue().set(redisCountKey, String.valueOf(initialCount));
            // 然后再进行自增操作
            redisTemplate.opsForValue().decrement(redisCountKey, 1);
        }

        redisTemplate.opsForSet().remove(redisRecordKey, String.valueOf(userId));

        // 4. 将“取消点赞”事件写入 Redis Stream，交由消费者异步处理
        Map<String, String> message = new HashMap<>();
        message.put("userId", userId.toString());
        message.put("postId", postId);
        message.put("action", "unlike");
        message.put("timestamp", String.valueOf(System.currentTimeMillis()));
        redisTemplate.opsForStream().add("stream:post:like", message);
        return Result.success(1,"取消点赞成功");
    }


    @Transactional
    @Override
    public boolean hasLiked(Long userId, String postId) {
        // Redis 键定义
        String redisRecordKey = "post:like:record:" + postId;

        // 检查 Redis 集合中是否已存在该用户的点赞记录
        Boolean alreadyLiked = redisTemplate.opsForSet().isMember(redisRecordKey, String.valueOf(userId));
        if (alreadyLiked != null && alreadyLiked) {
            return true;
        }else if(alreadyLiked==null){
            PostLike exist = postLikeMapper.selectByUserAndPost(userId, postId);
            if (exist != null) {
                return true;
            }
        }
        return false;
    }
    @Override
    public Result<?> getLikeRecord(String postId){
        List<PostLike> list = postLikeMapper.selectByPostId(postId);
        if(list.isEmpty()){
            return Result.error("该帖子点赞记录为空");
        }
        return Result.success(list);
    }

}

